package com.wm.blog_admin.service;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wm.blog_admin.controller.resp.BlogDetailResp;
import com.wm.blog_admin.controller.resp.BlogExportResp;
import com.wm.blog_admin.controller.resp.BlogResp;
import com.wm.blog_admin.controller.resp.CommentResp;
import com.wm.blog_admin.dao.*;
import com.wm.blog_admin.feign.PictureFeignClient;
import com.wm.blog_admin.query.TBlogQuery;
import com.wm.blog_common.base.BeanUtils;
import com.wm.blog_common.bean.PageHelper;
import com.wm.blog_common.bean.QueryPage;
import com.wm.blog_common.constatnt.CommonConstant;
import com.wm.blog_common.constatnt.ErrorConstant;
import com.wm.blog_common.domain.TBlogDO;
import com.wm.blog_common.entity.*;
import com.wm.blog_common.enums.CommentTypeEnum;
import com.wm.blog_common.enums.PublishFlag;
import com.wm.blog_common.exception.BusinessException;
import com.wm.blog_common.result.Result;
import com.wm.blog_common.util.CommonUtil;
import com.wm.blog_common.util.excel.ExcelUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 博客表 服务实现类
 * </p>
 *
 * @author wm_yu
 * @since 2020-03-24
 */
@Service
public class TBlogService {
    @Autowired
    private TBlogDAO tBlogDAO;

    @Autowired
    private TBlogSortDAO tBlogSortDAO;

    @Autowired
    private PictureFeignClient pictureFeignClient;

    @Autowired
    private TCommentDAO tCommentDAO;

    @Autowired
    private TUserDAO tUserDAO;

    @Autowired
    private TCollectDAO tcollectDAO;

    @Autowired
    private TRecommendDAO tRecommendDAO;

    /**
     * 根据ID查询
     * @param id
     * @return
     */
    public Result<TBlogDO> selectById(Long id){
        return Result.success(BeanUtils.copyProperties(tBlogDAO.getById(id), TBlogDO.class));
    }

    /**
    * 根据ID删除
    * @param id
    * @return
    */
    public Result deleteById(Long id){
        return tBlogDAO.removeById(id)? Result.success(): Result.failure();
    }

    /**
    * 添加
    * @param tBlog
    * @return
    */
    public Result insert(TBlog tBlog){
        return tBlogDAO.save(tBlog)? Result.success(): Result.failure();
    }

    /**
    * 修改
    * @param tBlog
    * @return
    */
    public Result update(TBlog tBlog){
        return tBlogDAO.updateById(tBlog)? Result.success(): Result.failure();
    }

    /**
    * 统计总数
    *
    * @param query
    * @return
    */
    public Result<Integer> count(TBlogQuery query) {
        return Result.success(tBlogDAO.count(this.combineQuery(query)));
    }

    /**
    * 列表查询
    * @param query
    * @return
    */
    public Result<List<TBlogDO>> list(TBlogQuery query){
        return Result.success(BeanUtils.copyListProperties(tBlogDAO.list(this.combineQuery(query)), TBlogDO.class));
    }
    /**
    * 分页查询
    * @param page
    * @return
    */
    public Result page(QueryPage page, TBlogQuery query){
        Page<TBlogDO> newPage = PageHelper.newPage(tBlogDAO.page(page, this.combineQuery(query)), TBlogDO.class);
        if(!ObjectUtils.isEmpty(newPage) && !CollectionUtils.isEmpty(newPage.getRecords())){
            List<TBlogDO> records = newPage.getRecords();
            List<BlogResp> respList = BeanUtils.copyListProperties(records, BlogResp.class);
            //分类id
            List<Long> sortIdList = respList
                    .stream()
                    .map(BlogResp::getBlogSortId)
                    .collect(Collectors.toList());
            //图片id
            List<Long> picIdList = respList
                    .stream()
                    .map(BlogResp::getFileId)
                    .collect(Collectors.toList());
            Map<Long, String> sortMap = tBlogSortDAO
                    .listByIds(sortIdList)
                    .stream()
                    .collect(Collectors.toMap(TBlogSort::getId, TBlogSort::getSortName));
            Map<Long, String> picMap = Optional.ofNullable(pictureFeignClient
                    .getByIdList(picIdList)
                    .getData())
                    .orElse(new ArrayList<>())
                    .stream()
                    .collect(Collectors.toMap(TFile::getId, TFile::getPicUrl));
            respList.forEach(x -> {
                x.setSortName(sortMap.getOrDefault(x.getBlogSortId(),null));
                x.setPictureUrl(picMap.getOrDefault(x.getFileId(),null));
            });
            //按照sort排序
            respList.sort((x,y) -> {
                Integer xSort = x.getSort();
                Integer ySort = y.getSort();
                return xSort.compareTo(ySort);
            });
            Page p = new Page();
            BeanUtils.copyProperties(newPage,p);
            p.setRecords(respList);
            return Result.success(p);
        }
        return Result.success(newPage);
    }

    /**
    * 组装查询条件
    *
    * @param query
    * @return
    */
    private QueryWrapper<TBlog> combineQuery(TBlogQuery query) {
        QueryWrapper<TBlog> wrapper = new QueryWrapper<>();
        Optional.ofNullable(query).ifPresent(x -> {
            Optional.ofNullable(x.getAdminId()).ifPresent(y -> {
                wrapper.eq("admin_id",y);
            });
            Optional.ofNullable(x.getOderByColumns()).filter(StringUtils::isNotEmpty).ifPresent(y -> {
                if(query.getOderFlag()){
                    wrapper.orderByAsc(y);
                }else{
                    wrapper.orderByDesc(y);
                }
            });
        });
        return wrapper;
    }

    public void export(TBlogQuery query, HttpServletResponse response) {
        //查询数据
        QueryWrapper<TBlog> wrapper = this.combineQuery(query);
        List<TBlog> blogList = Optional.ofNullable(tBlogDAO.list(wrapper)).orElse(new ArrayList<>());
        List<BlogExportResp> respList = BeanUtils.copyListProperties(blogList, BlogExportResp.class);
        if(!CollectionUtils.isEmpty(respList)){
            List<String> headerList = CommonUtil.getExcelHeaderList(BlogExportResp.class);
            ExcelUtil.downloadExcelFile(CommonConstant.BLOG_TILE,headerList,respList,response);
        }
    }


    public Result blogSortPie(Long adminId) {
        if(ObjectUtils.isEmpty(adminId)){
            return Result.failure(ErrorConstant.USER_ID_EMPTY);
        }
        TBlogQuery query = new TBlogQuery();
        query.setAdminId(adminId);
        query.setIsPublish(PublishFlag.PUBLISH.getValue());
        return Result.success(Optional.ofNullable(tBlogDAO.blogSortPie(query)).orElse(Collections.emptyList()));
    }


    /**
     * 查询博客详情
     * @param id
     * @return
     */
    public Result blogDetail(Long id) {
        Optional.ofNullable(id).orElseThrow(() -> new BusinessException(ErrorConstant.BLOG_ID_EMPTY));
        TBlog blog = Optional.ofNullable(tBlogDAO.getById(id)).orElse(new TBlog());
        BlogResp blogResp = new BlogResp();
        BeanUtils.copyProperties(blog,blogResp);
        //评论
        QueryWrapper<TComment> wrapper = new QueryWrapper<>();
        wrapper.eq("blog_id",id);
        BlogDetailResp resp = new BlogDetailResp();
        resp.setBlog(blogResp);
        //包含点赞 + 评论
        List<TComment> commentList = Optional
                .ofNullable(tCommentDAO.list(wrapper))
                .orElse(Collections.emptyList());
        if(!CollectionUtils.isEmpty(commentList)){
            //点赞总数
            int size = commentList
                    .stream()
                    .filter(x -> CommentTypeEnum.LIKE.getValue().equals(x.getType()))
                    .collect(Collectors.toList())
                    .size();
            blogResp.setLikeCount(size);
            //TODo 使用java8异步处理
            //构建点赞的map
            Map<Long, List<TComment>> map = commentList
                    .stream()
                    .filter(x -> CommentTypeEnum.LIKE.getValue().equals(x.getType()))
                    .collect(Collectors
                            .groupingBy(TComment::getUserId));
           //评论人的id,不包含点赞的
            List<Long> userIdList = commentList
                    .stream()
                    .filter(x -> CommentTypeEnum.COMMENT.getValue().equals(x.getType()))
                    .map(TComment::getUserId)
                    .collect(Collectors.toList());
            //查询评论人信息,  k -- userId  v --- username
            Map<Long, TUser> userMap = Optional
                    .ofNullable(tUserDAO
                            .listByIds(userIdList))
                    .orElse(Collections.emptyList()).stream().collect(Collectors.toMap(TUser::getId, v->v));

            List<CommentResp> respList = commentList
                    .stream()
                    .map(x -> {
                        CommentResp commentResp = new CommentResp();
                        BeanUtils.copyProperties(x, commentResp);
                        List list = map.getOrDefault(x.getUserId(), Collections.EMPTY_LIST);
                        commentResp.setLikeCount(list.size());
                        TUser user = userMap.getOrDefault(x.getUserId(), new TUser());
                        commentResp.setUserName(user.getUserName());
                        commentResp.setAvatar(user.getAvatar());
                        commentResp.setContent(x.getContent());
                        commentResp.setCreateTime(x.getCreateTime());
                        commentResp.setId(x.getId());
                        String time = CommonUtil.dealCommentTime(x.getCreateTime());
                        commentResp.setCommentTimeStr(time);
                        return commentResp;
                    })
                    .collect(Collectors.toList());
            resp.setCommentList(respList);
        }
        return Result.success(resp);
    }

    /**
     * 博客推荐
     * @param query
     * @return
     */
    public Result recommendBlog(TBlogQuery query) {
        query = Optional.ofNullable(query).orElse(new TBlogQuery());
        Optional.ofNullable(query.getId()).orElseThrow(() -> new BusinessException(ErrorConstant.BLOG_ID_EMPTY));
        //校验当前博客是否已经在推荐列表中
        QueryWrapper<TRecommend> wrapper = new QueryWrapper<>();
        wrapper.eq("recommend_id",query.getId());
        wrapper.last("limit 1");
        TRecommend recommend = Optional.ofNullable(tRecommendDAO.getOne(wrapper)).orElse(new TRecommend());
        if(!Objects.isNull(recommend.getId())){
            return Result.failure(ErrorConstant.BLOG_RECOMMEND_EXSIT);
        }
        //查询博客信息
        TBlog blog = Optional.ofNullable(tBlogDAO.getById(query.getId())).orElse(new TBlog());
        recommend.setRecommendId(query.getId());
        recommend.setAdminId(query.getAdminId());
        recommend.setTitle(blog.getTitle());
        return tRecommendDAO.save(recommend) ? Result.success(): Result.failure();
    }
}







